/**
 * @author 		chenc
 * @version 	1.0
 * @date 		2016.6.23
 *
 * @file 		sct/demux/tsdemux.h
 * @brief 		ts demux interface
 *
 * CTsDemux
 */
#ifndef SCT_DEMUX_TSDEMUX_H
#define SCT_DEMUX_TSDEMUX_H

#include "../mux/tsmux.h"

namespace sct
{

class CTsDemuxCallback;
class CTsDemux
{
public:
    class CPmt;
	class CPes
	{
	public:
		int64_t pts;///cloclk is:90000Hz
        int64_t dts;

		uint8_t* buf;
        uint32_t size;

		uint32_t len;
        uint32_t target_len;

		CTSMux::StreamType type;
        int pid;

        CPmt * pmt;
	};
	class CPmt
	{
	public:
		int64_t pcr;///90000hz
        int pcr_pid;

        int pid;
        int number;

		std::list<CPes *> pess;
    };

public:
	CTsDemux();
	~CTsDemux();

	void demux(const void * d);

	void addCallback(CTsDemuxCallback * callback) {mCallback = callback;}
	void delCallback(CTsDemuxCallback * callback) {mCallback = NULL;}

private:
    void parsePAT(const uint8_t * d);
    void addProgram(const int number, const int pid);

    CPmt* checkIfPmt(const int pid);
    void parsePMT(const uint8_t * d, CPmt*pmt);
    void addPes(CPmt*pmt, const int type, const int pid);

    CPmt* checkIfPcr(const int pid);
    void parsePcr(const uint8_t *d, CPmt*pmt);

    CPes* checkIfPes(const int pid);
    void parsePes(const uint8_t *d, CPes*pes);
private:
    std::list<CPmt*> mPmts;
    int mTsStreamID;

	CTsDemuxCallback * mCallback;
};

class CTsDemuxCallback
{
public:
	virtual ~CTsDemuxCallback() {}

    virtual void onRecvPesPacket(CTsDemux* caller, const CTsDemux::CPes * pes) {}
    virtual void onPcrUpdate(CTsDemux* caller, const CTsDemux::CPmt* pmt) {}

    virtual void onNewProgram(CTsDemux* caller, const CTsDemux::CPmt * pmt) {}
    virtual void onNewPes(CTsDemux* caller, const CTsDemux::CPes * pes) {}
};
}

#endif
